package com.wudgaby.study.jwtauth.support;

import com.wudgaby.study.jwtauth.config.TokenProperties;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Component
public class JWTHelper {
    @Autowired
    private TokenProperties tokenProperties;


    /**
     * 秘钥key
     */
    //private static final String SECRET_KEY = "fc295d965b81a7128281c187e7f5e439-cnns-ok-is-good";

    /**
     * 默认加密算法
     */
    //private static final SignatureAlgorithm defaultAlgorithm = SignatureAlgorithm.HS256;

    /**
     * 创建jwt
     * @param claimsMap
     * @param ttlMillis
     * @return
     */
    public String createJWT(Map<String, Object> claimsMap, long ttlMillis){
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        Key key = generateKey();

        JwtBuilder builder = Jwts.builder()
                                    .setId(UUID.randomUUID().toString())
                                    .setIssuedAt(now)
                                    .setClaims(claimsMap)
                                    .signWith(key, tokenProperties.getSignatureAlgorithm());

        if(ttlMillis >= 0){
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }

        return builder.compact();
    }

    /**
     * 创建jwt
     * @param claims
     * @param ttlMillis
     * @return
     */
    public String createJWT(Claims claims, long ttlMillis){
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        Key key = generateKey();

        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(now)
                .setClaims(claims)
                .signWith(key, tokenProperties.getSignatureAlgorithm());

        if(ttlMillis >= 0){
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }

        return builder.compact();
    }

    /**
     * 验证jwt
     */
    public boolean verifyJWT(String token) {
        //签名秘钥，和生成的签名的秘钥一模一样
        Key key = generateKey();

        try{
            Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token).getBody();
            return true;
        }catch (JwtException ex) {
            log.error("解析jwt失败. token : {}", token, ex);
            return false;
        }
    }

    /**
     * 解析jwt
     */
    public Claims parseJWT(String token) {
        //签名秘钥，和生成的签名的秘钥一模一样
        Key key = generateKey();

        try{
            Claims claims = Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token).getBody();
            return claims;
        }catch (ClaimJwtException ex) {
            log.error("解析jwt失败. token : {}", token, ex);
            return ex.getClaims();
        }
    }

    /**
     * 生成秘钥
     * @return
     */
    private Key generateKey() {
        byte[] secretKeyBytes = Base64.decodeBase64(tokenProperties.getSecretKey());
        return new SecretKeySpec(secretKeyBytes, tokenProperties.getSignatureAlgorithm().getJcaName());
    }
}
